package com.wlf.admin.system.controller;

import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.http.HtmlUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wlf.admin.common.config.SysConfig;
import com.wlf.admin.common.dto.Const;
import com.wlf.admin.common.dto.ParamPage;
import com.wlf.admin.common.quartz.QuartzService;
import com.wlf.admin.common.util.AjaxBean;
import com.wlf.admin.common.util.JSON;
import com.wlf.admin.system.domain.ScheduleJob;
import com.wlf.admin.system.domain.ScheduleLog;
import com.wlf.admin.system.service.ScheduleJobService;
import com.wlf.admin.system.service.ScheduleLogService;
import org.quartz.Scheduler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import java.util.List;

@RestController
@RequestMapping("/schedule")
public class ScheduleController {
    @Resource
    ScheduleJobService scheduleJobService;
    @Resource
    ScheduleLogService logService;
    @Resource
    private Scheduler scheduler;

    @GetMapping("/main")
    ModelAndView indexHtml() {
        ModelAndView view = new ModelAndView("schedule/index");
        view.addObject("taskName", Const.TaskBeanKey);
        view.addObject("jobTypeList", List.of(Const.JobType.values()));
        view.addObject("intervalUnitList", List.of(Const.IntervalUnit.values()));
        return view;
    }


    @GetMapping("/addForm")
    ModelAndView addFormHtml() {
        ModelAndView view = new ModelAndView("schedule/add");
        view.addObject("beanNameList", scheduleJobService.getBeanNameList(Const.TaskBeanKey));
        view.addObject("jobTypeList", List.of(Const.JobType.values()));
        view.addObject("intervalUnitList", List.of(Const.IntervalUnit.values()));
        return view;
    }

    @GetMapping("/editForm")
    ModelAndView editFormHtml(Long id) {
        ModelAndView view = new ModelAndView("schedule/edit");
        view.addObject("beanNameList", scheduleJobService.getBeanNameList(Const.TaskBeanKey));
        view.addObject("job", scheduleJobService.getById(id));
        view.addObject("jobTypeList", List.of(Const.JobType.values()));
        view.addObject("intervalUnitList", List.of(Const.IntervalUnit.values()));
        return view;
    }

    /**
     * 开启或停止定时任务
     *
     * @return 操作结果
     */
    @GetMapping("/updateStatus")
    AjaxBean updateStatus(Long id) {
        ScheduleJob job = scheduleJobService.getById(id);
        if (job.getStatus() == 0) {
            job.setStatus(1);
            QuartzService.pauseJob(scheduler, id);
        } else {
            job.setStatus(0);
            QuartzService.resumeJob(scheduler, id);
        }
        return AjaxBean.getByBool(scheduleJobService.updateById(job), "操作成功", "操作失败");
    }

    /**
     * 获取任务列表
     *
     * @param job       查询参数
     * @param paramPage 分页
     * @return 任务列表
     */
    @PostMapping("/list")
    AjaxBean list(ScheduleJob job, ParamPage paramPage) {
        LambdaQueryWrapper<ScheduleJob> wrapper = new LambdaQueryWrapper<>();
        if (StrUtil.isNotBlank(job.getName())) {
            wrapper.like(ScheduleJob::getName, job.getName());
        }
        Page<ScheduleJob> page = scheduleJobService.page(paramPage.init(), wrapper);
        return AjaxBean.getOkPage(page);
    }

    @PostMapping("/add")
    AjaxBean add(ScheduleJob job) {
        job.setId(IdWorker.getId());
        job.setCronExpression(job.getCronExpression().trim());
        QuartzService.createJob(scheduler, job);
        return AjaxBean.getByBool(scheduleJobService.save(job));
    }


    @PostMapping("/update")
    AjaxBean update(ScheduleJob job) {
        job.setCronExpression(job.getCronExpression().trim());
        QuartzService.updateJob(scheduler, job);
        return AjaxBean.getByBool(scheduleJobService.updateById(job));
    }


    /**
     * 根据任务ID运行一个任务
     *
     * @param id 任务ID
     * @return 运行状态
     */
    @GetMapping("/run")
    AjaxBean run(Long id) {
        ScheduleJob job = scheduleJobService.getById(id);
        QuartzService.run(scheduler, job);
        return AjaxBean.getOkMsg();
    }

    /**
     * 删除一个任务
     *
     * @param id 任务ID
     * @return 删除结果
     */
    @PostMapping("/del")
    AjaxBean del(Long id) {
        QuartzService.deleteJob(scheduler, id);
        scheduleJobService.removeById(id);
        logService.lambdaUpdate().eq(ScheduleLog::getJobId, id).remove();
        return AjaxBean.getOkMsg();
    }

    @PostMapping("/delAll")
    AjaxBean delAll(String ids) {
        List<Long> longs = JSON.parseArray(HtmlUtil.unescape(ids), Long.class);
        for (Long aLong : longs) {
            QuartzService.deleteJob(scheduler, aLong);
            scheduleJobService.removeById(aLong);
            logService.lambdaUpdate().eq(ScheduleLog::getJobId, aLong).remove();
        }
        return AjaxBean.getOkMsg();
    }


    @GetMapping("/logForm")
    ModelAndView logForm(Long id) {
        ModelAndView view = new ModelAndView("schedule/log");
        view.addObject("id", id);
        return view;
    }
    /**
     * 功能描述: 三方Cron表达式写法地址
     * @author wlf 2023/12/1 17:42
     */
    @GetMapping("/cronForm")
    ModelAndView cronForm() {
        ModelAndView view = new ModelAndView("schedule/cron");
        String cronUrl = SpringUtil.getBean(SysConfig.class).getCronUrl();
        view.addObject("cronUrl", cronUrl);
        return view;
    }

    /**
     * 获取任务日子列表
     *
     * @param paramPage 分页
     * @return 日志列表
     */
    @PostMapping("/logList")
    AjaxBean logList(Long id, ParamPage paramPage) {
        LambdaQueryWrapper<ScheduleLog> wrapper = new LambdaQueryWrapper<>();
        if (id != null) {
            wrapper.eq(ScheduleLog::getJobId, id);
        }
        wrapper.orderByDesc(ScheduleLog::getId);
        Page<ScheduleLog> page = logService.page(paramPage.init(), wrapper);
        for (ScheduleLog record : page.getRecords()) {
            record.setJobName(scheduleJobService.getById(record.getJobId()).getName());
        }
        return AjaxBean.getOkPage(page);
    }

    /**
     * 删除任务执行日志
     */
    @PostMapping("/logDel")
    AjaxBean logDel(Const.DelType type, Long id) {
        return logService.del(type, id);
    }

    @PostMapping("/logDelAll")
    AjaxBean logDelAll(String ids) {
        return AjaxBean.getByBool(logService.removeBatchByIds(JSON.parseArray(HtmlUtil.unescape(ids), Long.class)));
    }

}
